package com.kun.dynamic.config;

import com.kun.dynamic.aop.DynamicDsAspect;
import com.kun.dynamic.core.DynamicDataSource;
import com.kun.dynamic.properties.DynamicDataSourceProperties;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.Map;

/**
 * DataSource存在则不会实例化 HikariDataSource
 * 因为我们写的配置文件不是DataSourceProperties 如果
 * 实例化HikariDataSource就会报错【DataSourceProperties没有任何配置信息】
 * 因此我们要先进行实例化我们自己写的DynamicDataSource这样 就有了DataSource这个Bean
 * 所以下面条件不满足就不会进行实例化HikariDataSource
 *
 * @Configuration(proxyBeanMethods = false)
 * @ConditionalOnClass(HikariDataSource.class)
 * @ConditionalOnMissingBean(DataSource.class)
 * @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
 * matchIfMissing = true)
 * static class Hikari {
 * @Bean
 * @ConfigurationProperties(prefix = "spring.datasource.hikari")
 * HikariDataSource dataSource(DataSourceProperties properties) {
 * HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
 * if (StringUtils.hasText(properties.getName())) {
 * dataSource.setPoolName(properties.getName());
 * }
 * return dataSource;
 * }
 * <p>
 * }
 */
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(DynamicDataSourceProperties.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
public class DynamicDataSourceAutoConfig {

    /**
     * 动态数据源配置
     *
     * @param dynamicDataSourceProperties 动态数据源配置
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public DynamicDataSource dynamicDataSource(DynamicDataSourceProperties dynamicDataSourceProperties) {
        Map<String, DynamicDataSourceProperties.DataSourceProperties> dataSource = dynamicDataSourceProperties.getDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        dataSource.forEach((key, value) -> targetDataSources.put(key, hikariDataSource(value)));
        DynamicDataSourceProperties.DataSourceProperties master = dataSource.get("master");
        Assert.notNull(master,"必须有一个 key 为 master的数据源");
        HikariDataSource hikariDataSource = hikariDataSource(master);
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(hikariDataSource);
        return dynamicDataSource;
    }


    private HikariDataSource hikariDataSource(DynamicDataSourceProperties.DataSourceProperties dataSourceProperties) {
        HikariConfig hikariConfig = getHikariConfig(dataSourceProperties.getUsername(),
                dataSourceProperties.getPassword(), dataSourceProperties.getUrl(), dataSourceProperties.getDriverClassName());
        return new HikariDataSource(hikariConfig);
    }

    private HikariConfig getHikariConfig(String username, String password, String url, String driverClassName) {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setUsername(username);
        hikariConfig.setPassword(password);
        hikariConfig.setJdbcUrl(url);
        hikariConfig.setDriverClassName(driverClassName);
        return hikariConfig;
    }


    @Bean
    public DynamicDsAspect dynamicDsAspect() {
        return new DynamicDsAspect();
    }
}